package uk.ac.lkl.common.allocator.ui;



import java.awt.Point;
import java.awt.event.MouseEvent;
//import java.util.ArrayList;

//import javax.swing.event.MouseInputAdapter;

import uk.ac.lkl.common.allocator.AllocatorModel;



/**
 * Make this more generic than just for Switched view.
 * 
 * 
 * 
 * @author Darren Pearce
 * @version $Revision: 620 $
 * @version $Date: 2008-02-20 00:46:53 +0000 (Wed, 20 Feb 2008) $
 * 
 */
public class AllocatorController<O> extends AbstractAllocatorController<O> {

    private SwitchingAllocatorView<O> allocatorView;

    private Point dragStart;

    private Point dragPoint = new Point();

    private Dragger<O> createDragger;

    private Dragger<O> moveDragger;

    private Dragger<O> dragger;

    // indicates whether a drag operation too place during a sequence
    // of press/drag*/release.
    boolean dragged;


//    public AllocatorController(SwitchingAllocatorView<O> allocatorView) {
//        this.allocatorView = allocatorView;
//        allocatorView.addMouseListener(this);
//        allocatorView.addMouseMotionListener(this);
//        createDragger = new CreateDragger<O>(allocatorView);
//        moveDragger = new MoveDragger<O>(allocatorView);
//    }


    public void install(AllocatorView<O> view) {
        SwitchingAllocatorView<O> allocatorView = (SwitchingAllocatorView<O>) view;
        this.allocatorView = allocatorView;
        allocatorView.addMouseListener(this);
        allocatorView.addMouseMotionListener(this);
        createDragger = new CreateDragger<O>(allocatorView);
        moveDragger = new MoveDragger<O>(allocatorView);
    }


    public void uninstall(AllocatorView<O> view) {
        if (view != allocatorView)
            return;

        allocatorView.removeMouseListener(this);
        allocatorView.removeMouseMotionListener(this);
    }


    public final void mousePressed(MouseEvent e) {
        int x = e.getX();
        int y = e.getY();
        Point location = allocatorView.getCell(x, y);

        int column = location.x - 1;
        int row = location.y;

        // ignore header cells and rows out of bounds
        if (row <= 0 || column < 0)
            return;

        if (row > allocatorView.getNumRows()
                || column > allocatorView.getNumColumns())
            return;

        // initialise both
        dragStart = location;
        dragPoint.setLocation(location);
        dragged = false;

        O object = allocatorView.getObject(row);

        int allocation = allocatorView.getAllocator().getAllocation(object,
                                                                    column);

        if (allocation == 0) {
            dragger = createDragger;
        }
        else {
            dragger = moveDragger;
        }

        dragger.processMousePressed(object, row, column);
    }


    public void mouseDragged(MouseEvent e) {
        // do nothing if not dragging
        if (dragStart == null)
            return;

        dragged = true;

        // do nothing if still in same (horizontal) cell
        int x = e.getX();
        int y = e.getY();
        Point location = allocatorView.getCell(x, y);

        // use row as in dragStart
        int row = dragStart.y;
        int column = location.x - 1;

        O object = allocatorView.getObject(row);

        if (column < 0 || column > allocatorView.getNumColumns())
            return;

        dragPoint.setLocation(location);

        // delegate to dragger to decide what to do
        dragger.processMouseDragged(object, row, column);
    }


    public void mouseReleased(MouseEvent e) {
        if (dragStart == null)
            return;

        // dragger.processMouseRelease(

        // if not dragged, is a simple click so do create/delete
        // could factor this out

        int row = dragStart.y;
        int column = dragStart.x - 1;

        dragStart = null;

        O object = allocatorView.getObject(row);

        if (dragged) {
            allocatorView.clearMobileCells(object);
            return;
        }

        AllocatorModel<O> allocator = allocatorView.getAllocator();

        int allocation = allocator.getAllocation(object, column);


        if (allocation == 0)
            allocator.addAllocation(object, column);
        else
            allocator.unallocate(object, column);
    }

};
